package main

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"os"
	"pulsar_study/domain/entity"
	"time"
)

var (
	firstNames     = []string{"伟", "芳", "娜", "秀英", "敏", "静", "丽", "强", "磊", "洋"}
	lastNames      = []string{"张", "王", "李", "赵", "刘", "陈", "杨", "黄", "周", "吴"}
	cities         = []string{"北京", "上海", "深圳", "杭州", "成都", "重庆", "武汉", "西安", "南京"}
	provinces      = []string{"北京市", "上海市", "广东省", "浙江省", "四川省", "重庆市", "湖北省", "陕西省", "江苏省"}
	productNames   = []string{"智能手机", "笔记本电脑", "无线耳机", "智能手表", "运动鞋", "T恤衫", "咖啡机", "护肤套装", "背包", "台灯"}
	categories     = []string{"电子产品", "服装配饰", "家居生活", "美妆护肤", "运动户外"}
	paymentMethods = []string{"支付宝", "微信支付", "银行卡", "信用卡", "Apple Pay"}
	statuses       = []string{"已完成", "待发货", "待付款", "已取消", "退款中"}
	comments       = []string{"质量很好，物流很快！", "性价比高，推荐购买。", "一般般，没有想象中好。", "非常满意，会回购。", "有点小瑕疵，但还能接受。"}
	allTags        = []string{"新品", "热销", "特价", "包邮", "限量"}
)

// generateUUID 生成一个简单的伪UUID
func generateUUID() string {
	bytes := make([]byte, 16)
	rand.Read(bytes) // 使用 crypto/rand 更安全，但 math/rand 对此场景足够快
	return fmt.Sprintf("%x-%x-%x-%x-%x", bytes[0:4], bytes[4:6], bytes[6:8], bytes[8:10], bytes[10:16])
}

// generatePhoneNumber 生成一个随机的手机号码
func generatePhoneNumber() string {
	return fmt.Sprintf("1%010d", rand.Intn(10000000000))
}

// generateIPAddress 生成一个随机的IPv4地址
func generateIPAddress() string {
	return fmt.Sprintf("%d.%d.%d.%d", rand.Intn(256), rand.Intn(256), rand.Intn(256), rand.Intn(256))
}

// generateFakeUser 生成一个包含随机数据的User实例
func generateFakeUser() *entity.User {
	userID := rand.Intn(10000000)
	userName := lastNames[rand.Intn(len(lastNames))] + firstNames[rand.Intn(len(firstNames))]
	cityIndex := rand.Intn(len(cities))
	city := cities[cityIndex]
	province := provinces[cityIndex] // 简单关联城市和省份
	productName := productNames[rand.Intn(len(productNames))]
	category := categories[rand.Intn(len(categories))]

	// 随机生成评论，有20%的概率为空
	var commentPtr *string
	if rand.Intn(100) < 20 {
		commentPtr = nil
	} else {
		comment := comments[rand.Intn(len(comments))]
		commentPtr = &comment
	}

	// 随机生成标签
	tagsCount := rand.Intn(4) + 1 // 1到4个标签
	tags := make([]string, tagsCount)
	for i := 0; i < tagsCount; i++ {
		tags[i] = allTags[rand.Intn(len(allTags))]
	}

	now := time.Now()

	return &entity.User{
		ID:            generateUUID(),
		Timestamp:     now.Format(time.RFC3339),
		UserID:        userID,
		UserName:      userName,
		Email:         fmt.Sprintf("user%d@example.com", userID),
		Phone:         generatePhoneNumber(),
		Age:           rand.Intn(48) + 18, // 年龄 18-65
		Gender:        []string{"男", "女"}[rand.Intn(2)],
		City:          city,
		Province:      province,
		Address:       fmt.Sprintf("%s%s%s%d号", province, city, "某某区", rand.Intn(999)+1),
		IPAddress:     generateIPAddress(),
		OrderID:       generateUUID(),
		ProductID:     generateUUID(),
		ProductName:   productName,
		Category:      category,
		Price:         rand.Float64()*1000 + 10, // 价格 10-1010
		Quantity:      rand.Intn(5) + 1,         // 数量 1-5
		Discount:      rand.Float64() * 0.5,     // 折扣 0-0.5
		PaymentMethod: paymentMethods[rand.Intn(len(paymentMethods))],
		Status:        statuses[rand.Intn(len(statuses))],
		Rating:        rand.Intn(5) + 1, // 评分 1-5
		Comment:       commentPtr,
		Tags:          tags,
		IsMember:      rand.Intn(2) == 1, // 50%概率是会员
		Points:        rand.Intn(5000),
		CreatedAt:     now.Add(-time.Duration(rand.Intn(86400)) * time.Second).Format(time.RFC3339), // 创建时间在过去24小时内
	}
}

func main() {
	// 初始化随机数种子
	rand.Seed(time.Now().UnixNano())

	const numRecords = 1_000_000
	const fileName = "users.jsonl"

	fmt.Printf("开始生成 %d 条数据到文件 %s...\n", numRecords, fileName)

	// 创建并打开文件
	file, err := os.Create(fileName)
	if err != nil {
		fmt.Printf("无法创建文件: %s\n", err)
		return
	}
	defer file.Close() // 确保在函数退出时关闭文件

	// 创建一个JSON编码器，直接写入文件，比Marshal更高效
	encoder := json.NewEncoder(file)

	startTime := time.Now()
	for i := 0; i < numRecords; i++ {
		user := generateFakeUser()

		// 将User对象编码为JSON并写入文件，Encoder会自动添加换行符
		if err := encoder.Encode(user); err != nil {
			fmt.Printf("编码数据时出错 (记录 %d): %s\n", i+1, err)
			return
		}

		// 每生成10万条记录，打印一次进度
		if (i+1)%100000 == 0 {
			fmt.Printf("已生成 %d / %d 条记录...\n", i+1, numRecords)
		}
	}

	duration := time.Since(startTime)
	fmt.Printf("成功！所有 %d 条数据已写入 %s。\n", numRecords, fileName)
	fmt.Printf("总耗时: %s\n", duration)
}
